﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using DirectShowLib;

namespace PlayCap.Wpf
{
   public class CameraCapturer1
    {
        private IBaseFilter theVideoDevice;
        private IBaseFilter baseGrabFlt;
        private int videoHeight;
        private int videoWidth;
        private int videoStride;
        private int WM_GRAPHNOTIFY;
        private ICaptureGraphBuilder2 m_captureGraphBuilder;
        private IAMVideoControl m_VidControl;
        private IVideoWindow m_videoWindow;
        private IMediaControl m_mediaControl;
        private IGraphBuilder m_graphBuilder;
        private IMediaEventEx m_mediaEventEx;
        private IntPtr hwnVideoWindowOwner;
        private IntPtr hwnPropertyPageOwner;
        private bool m_IsPreview;

       
        //1、获取视频采集设备IBaseFilter接口对象的方法

        //获取所有视频设备名称
        public ArrayList GetVideoInputDevice()
        { return GetDeviceCollection(FilterCategory.VideoInputDevice); }
        private ArrayList GetDeviceCollection(Guid DeviceType)
        {
            ArrayList returnString = new ArrayList();
            foreach (DsDevice ds in DsDevice.GetDevicesOfCat(DeviceType))
            {
                returnString.Add(ds.Name);
            }
            return returnString;
        }

        //通过获取到的视频设备名称设置采集设备的IBaseFilter对象
        public bool SetVideoInputDevice(string VideoInputDeviceName)
        {    //创建视频输入设备接口
            theVideoDevice = CreateFilter(FilterCategory.VideoInputDevice, VideoInputDeviceName);
            return true;
        }
        //通过过滤器类型和过滤器名称获取IBaseFilter接口
        private IBaseFilter CreateFilter(Guid category, string friendlyname)
        {
            object source = null;
            Guid iid = typeof(IBaseFilter).GUID;
            foreach (DsDevice device in DsDevice.GetDevicesOfCat(category))
            {
                if (device.Name.CompareTo(friendlyname) == 0)
                {
                    device.Mon.BindToObject(null, null, ref iid, out source);
                    break;
                }
            }

            return (IBaseFilter)source;
        }

        //2、初始化基本的接口对象

        private void InitInterfaces()
        {
            int hr = 0;

            // 获取IGraphBuilder接口对象
            this.m_graphBuilder = (IGraphBuilder)new FilterGraph();
            //获取ICaptureGraphBuilder2接口对象
            this.m_captureGraphBuilder = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
            //获取m_graphBuilder 接口对象的IMediaControl对象
            this.m_mediaControl = (IMediaControl)this.m_graphBuilder;
            //获取m_graphBuilder 接口对象的IVideoWindow对象
            this.m_videoWindow = (IVideoWindow)this.m_graphBuilder;
            //获取m_graphBuilder 接口对象的IMediaEventEx对象
            this.m_mediaEventEx = (IMediaEventEx)this.m_graphBuilder;
            //设置ICaptureGraphBuilder2的IGraphBuilder接口对象为当前对象
            hr = this.m_captureGraphBuilder.SetFiltergraph(this.m_graphBuilder);
            DsError.ThrowExceptionForHR(hr);
            //注册事件到应用程序的窗体上
            hr = this.m_mediaEventEx.SetNotifyWindow(this.hwnPropertyPageOwner, WM_GRAPHNOTIFY, IntPtr.Zero);
            DsError.ThrowExceptionForHR(hr);
        }

        //3、开始视频预览
        public void VideoPreview()
        {
            try
            {

                int hr = 0;
                hr = this.m_graphBuilder.AddFilter(theVideoDevice, "Video Capture");
                DsError.ThrowExceptionForHR(hr);

                // 通过theVideoDevice（IBaseFilter）视频接口对象的Preview Pin预览
                hr = this.m_captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, theVideoDevice, null, null);
                DsError.ThrowExceptionForHR(hr);
                var

                                //插入SampleGrabber 
                                m_pinStill = DsFindPin.ByCategory(theVideoDevice, PinCategory.Still, 0);
                if (m_pinStill == null)
                {
                    m_pinStill = DsFindPin.ByCategory(theVideoDevice, PinCategory.Capture, 0);
                }


                // 获取theVideoDevice的IAMVideoControl对象，对于具有Still Pin的对象可以获到，采集设备不具备Still Pin，那么该对象将为Null
                m_VidControl = theVideoDevice as IAMVideoControl;

                // 设置采集视频参数
                if (this.videoHeight + this.videoWidth + this.videoStride > 0)
                {
                    SetConfigParms(m_pinStill, this.videoWidth, this.videoHeight, 24);
                }

                var

                                //开始拍照功能所需的接口对象
                                // 获得SampleGrabber对象接口
                                sampGrabber = new SampleGrabber() as ISampleGrabber;

                // 配置sample grabber
                baseGrabFlt = sampGrabber as IBaseFilter;
                ConfigureSampleGrabber(sampGrabber);

                // 将sample grabber添加到图形过滤器中
                hr = m_graphBuilder.AddFilter(baseGrabFlt, "Ds.NET Grabber");
                DsError.ThrowExceptionForHR(hr);

                //通过渲染将采集设备的相关输出Pin与sample grabber对象的输入Pin连接起来
                //如果采集设备提供Still Pin，则通过Still Pin连接，否则直接使用Capture Pin连接
                if (m_VidControl != null)
                {
                    hr = this.m_captureGraphBuilder.RenderStream(PinCategory.Still, MediaType.Video, theVideoDevice, null, baseGrabFlt);
                    DsError.ThrowExceptionForHR(hr);

                }
                else
                {
                    hr = this.m_captureGraphBuilder.RenderStream(PinCategory.Capture, MediaType.Video, theVideoDevice, null, baseGrabFlt);
                    DsError.ThrowExceptionForHR(hr);
                }
                //设置抓取图片相关参数
                SaveSizeInfo(sampGrabber);
                //拍照功能所需的接口对象添加结束


                // 开始将视频窗口绑定到主窗体上
                hr = this.m_videoWindow.put_Owner(this.hwnVideoWindowOwner);
                DsError.ThrowExceptionForHR(hr);

                hr = this.m_videoWindow.put_WindowStyle(WindowStyle.Child | WindowStyle.ClipChildren);
                DsError.ThrowExceptionForHR(hr);

                if (this.m_videoWindow != null)
                {
                    this.m_videoWindow.SetWindowPosition(0, 0, this.videoWidth, this.videoHeight);
                }


                hr = this.m_videoWindow.put_Visible(OABool.True);
                DsError.ThrowExceptionForHR(hr);

                // 开始预览采集设备采集到的视频
                hr = this.m_mediaControl.Run();

                DsError.ThrowExceptionForHR(hr);
                m_IsPreview = true;
            }
            catch
            {
                m_IsPreview = false;
                throw new Exception("VideoPreview函数出现异常，视频预览失败！");

            }
        }

        private void SaveSizeInfo(ISampleGrabber sampGrabber)
        {
            throw new NotImplementedException();
        }

        private void SetConfigParms(object m_pinStill, int videoWidth, int videoHeight, int v)
        {
            throw new NotImplementedException();
        }

        private void ConfigureSampleGrabber(ISampleGrabber sampGrabber)
        {
            throw new NotImplementedException();
        }
    }
}
